import { DoCheck, Directive, OnInit, ElementRef, NgZone, Input, OnChanges, SimpleChanges, OnDestroy } from '@angular/core';
import { ScrollBar } from '../lib/scrollbar';
import { useResizeObserver } from '../../util';

@Directive({
  selector: '[bzScrollbar]',
})
export class BzScrollbarDirective implements DoCheck, OnInit, OnChanges, OnDestroy {
  @Input() public resizeTargetSelector: string;

  /**
     * 滚轮滚动速度
     */
  @Input() public speed = 2;
  /**
     * 垂直滚动条靠左的偏移量
     */
  @Input() public offsetYLeft: number;
  /**
   * 垂直滚动条靠右的偏移量
   */
  @Input() public offsetYRight: number;
  /**
   * 垂直滚动条靠上的偏移量
   */
  @Input() public offsetYTop: number;
  /**
   * 垂直滚动条靠下的偏移量
   */
  @Input() public offsetYBottom: number;
  /**
   * 水平滚动条靠上的偏移量
   */
  @Input() public offsetXTop: number;
  /**
    * 水平滚动条靠下的偏移量
    */
  @Input() public offsetXBottom: number;
  /**
   * 水平滚动条靠左的偏移量
   */
  @Input() public offsetXLeft: number;
  /**
    * 水平滚动条靠右的偏移量
    */
  @Input() public offsetXRight: number;

  private scrollbar: ScrollBar;
  private timeout;
  private resizeObserver;

  constructor(
    private elementRef: ElementRef,
    private zone: NgZone) { }

  ngOnChanges(changes: SimpleChanges): void {
    if (useResizeObserver && changes.resizeTargetSelector) {
      if (this.resizeObserver) {
        if (changes.resizeTargetSelector.previousValue) {
          this.resizeObserver.disconnect();
        }
      } else {
        this.resizeObserver = new (<any>window).ResizeObserver(this.updateView.bind(this));
      }

      if (changes.resizeTargetSelector.currentValue) {
        this.zone.runOutsideAngular(() => {
          setTimeout(() => {
            const targets = this.elementRef.nativeElement.querySelectorAll(changes.resizeTargetSelector.currentValue);
            targets.forEach(ele => {
              this.resizeObserver.observe(ele, { box: 'border-box' });
            });
          }, 300);
        });
      }
    }
  }

  ngOnInit(): void {
    const option = {
      speed: this.speed,
      offsetYLeft: this.offsetYLeft,
      offsetYRight: this.offsetYRight,
      offsetYTop: this.offsetYTop,
      offsetYBottom: this.offsetYBottom,
      offsetXTop: this.offsetXTop,
      offsetXBottom: this.offsetXBottom,
      offsetXLeft: this.offsetXLeft,
      offsetXRight: this.offsetXRight
    };
    this.zone.runOutsideAngular(() => {
      this.scrollbar = new ScrollBar(this.elementRef.nativeElement, option as any);
    });
  }

  updateView() {
    this.zone.runOutsideAngular(() => {
      if (this.timeout) {
        clearTimeout(this.timeout);
      }

      this.timeout = setTimeout(() => {
        this.scrollbar.updateView();
        this.timeout = undefined;
      }, 500);
    });
  }

  ngOnDestroy(): void {
    if (this.resizeObserver) {
      this.resizeObserver.disconnect();
    }
  }

  ngDoCheck(): void {
    // if (this.scrollbar && !this.timeout) {
    //   this.zone.runOutsideAngular(() => {
    //     this.timeout = setTimeout(() => {
    //       this.scrollbar.updateView();
    //       this.timeout = undefined;
    //     }, 500);
    //   });
    // }
  }
}
